package com.gk.panda.apis.patrol.commons;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @Author：xxz
 * @Create: 2022/11/2 16:50
 */
@Data
@Component
public class RedisUtils {
  @Autowired
  private RedisTemplate<String, Object> redisTemplate;
  @Autowired
  private ValueOperations<String, String> valueOperations;
  @Autowired
  private HashOperations<String, String, Object> hashOperations;
  @Autowired
  private ListOperations<String, Object> listOperations;
  @Autowired
  private SetOperations<String, Object> setOperations;
  @Autowired
  private ZSetOperations<String, Object> zSetOperations;
  /** 默认过期时长，单位：秒 */
  public final static long DEFAULT_EXPIRE = 60 * 60 * 24;
  /** 不设置过期时长 */
  public final static long NOT_EXPIRE = -1;

  /**
   * 根据指定前缀获取keys
   */
  public Set<String> getKeysByPre(String pattern){
    return redisTemplate.keys(pattern+"*");
  }

  /**
   * 放入list表,左进
   */
  public void setListData(String key, Object value, long expire) {
    listOperations.leftPush(key, value);
    if(expire != NOT_EXPIRE) {
      redisTemplate.expire(key, expire, TimeUnit.SECONDS);
    }
  }

  /**
   * 取出list表数据,右出
   */
  public Object getListData(String key) {
    return listOperations.rightPop(key);
  }

  /**
   * 获取list表数据量
   */
  public Long getListDataSize(String key) {
    return listOperations.size(key);
  }

  /**
   * 放入hash表
   */
  public void setHash(String key, String hashKey, Object value, long expire) {
    hashOperations.put(key, hashKey, value);
    if(expire != NOT_EXPIRE) {
      redisTemplate.expire(key, expire, TimeUnit.SECONDS);
    }
  }

  /**
   * 获取hash表所有keys
   */
  public Set<String> getHashKeys(String key) {
    return hashOperations.keys(key);
  }

  /**
   * 获取hash表中所有元素的value
   */
  public List<Object> getHashValues(String key) {
    return hashOperations.values(key);
  }

  /**
   * 获取hash表中的所有元素
   */
  public Map<String, Object> getHashEntries(String key) {
    return hashOperations.entries(key);
  }
  /**
   * 从hash表取出
   */
  public Object getHash(String key, String hashKey) {
    return hashOperations.get(key, hashKey);
  }

  public void set(String key, Object value, long expire) {
    valueOperations.set(key, toJson(value));
    if (expire != NOT_EXPIRE) {
      redisTemplate.expire(key, expire, TimeUnit.SECONDS);
    }
  }

  public void set(String key, Object value) {
    set(key, value, DEFAULT_EXPIRE);
  }

  public <T> T get(String key, Class<T> clazz, long expire) {
    String value = valueOperations.get(key);
    if (expire != NOT_EXPIRE) {
      redisTemplate.expire(key, expire, TimeUnit.SECONDS);
    }
    return value == null ? null : fromJson(value, clazz);
  }

  public <T> T get(String key, Class<T> clazz) {
    return get(key, clazz, NOT_EXPIRE);
  }

  public String get(String key, long expire) {
    String value = valueOperations.get(key);
    if (expire != NOT_EXPIRE) {
      redisTemplate.expire(key, expire, TimeUnit.SECONDS);
    }
    return value;
  }

  public String get(String key) {
    return get(key, NOT_EXPIRE);
  }

  public void delete(String key) {
    redisTemplate.delete(key);
  }

  public void deleteBathch(Set<String> keys) {
    redisTemplate.delete(keys);
  }

  /**
   * Object转成JSON数据
   */
  private String toJson(Object object) {
    if (object instanceof Integer || object instanceof Long || object instanceof Float
            || object instanceof Double || object instanceof Boolean || object instanceof String) {
      return String.valueOf(object);
    }
    return JSON.toJSONString(object);
  }

  /**
   * JSON数据，转成Object
   */
  private <T> T fromJson(String json, Class<T> clazz) {
    return JSONObject.parseObject(json, clazz);
  }

  /**
   *将指定Key的Value原子性的增加increment。如果该Key不存在，其初始值为0，在incrby之后其值为increment。
   * 如果Value的值不能转换为整型值，如Hi，该操作将执行失败并抛出相应异常。操作成功则返回增加后的value值。
   * @param key
   * @param increment
   * @return
   */
  public long incrby(String key,long increment){
    if(null==key){
      throw new IllegalArgumentException("参数错误 key 不能为空!");
    }
    return redisTemplate.opsForValue().increment(key,increment);
  }
}
